home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
3D Images
/
3D Images.iso
/
programs
/
amiga
/
mpegutils
/
tools
/
src
/
ppm2cyuv.c
< prev
Wrap
C/C++ Source or Header
|
1995-01-12
|
8KB
|
284 lines
/*************************************************************
Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
Group. If you use this software, you agree to the following: This
program package is purely experimental, and is licensed "as is".
Permission is granted to use, modify, and distribute this program
without charge for any purpose, provided this license/ disclaimer
notice appears in the copies. No warranty or maintenance is given,
either expressed or implied. In no event shall the author(s) be
liable to you or a third party for any special, incidental,
consequential, or other damages, arising out of the use or inability
to use the program for any purpose (or the loss of data), even if we
have been advised of such possibilities. Any public reference or
advertisement of this source code should refer to it as the Portable
Video Research Group (PVRG) code, and not by any author(s) (or
Stanford University) name.
*************************************************************/
/*
************************************************************
ppm2cyuv.c
This program separates a raw ppm input file into component YUV files
with a sampling ratio of 4:1:1 (the same pattern as MPEG 4:2:0). The
output is placed in .Y .U .V by default.
The ppm description and files are part of Jef Poskanzer's PBMPLUS
library. This is just a short-cut program to do a simple YUV
conversion.
-----
Modifications by Son H. Le on 01-Sep-93
o replaced all exit(-1) with exit(0)
o added exit(0) after convertRGB2YUV()
o added #include <stdlib.h> and <string.h>
o added prototype convertRGB2YUV()
************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PPM_MAGIC1 'P'
#define PPM_MAGIC2 '3'
#define RPPM_MAGIC2 '6'
#define FIXNUM 16
#define FIX(a,b) ((int)((a)*(1<<(b))))
#define UNFIX(a,b) ((a+(1<<(b-1)))>>(b))
/* Approximate 255 by 256 */
#define CCIRUV(x) (((((x)-128)*224)>>8)+128)
#define CCIRY(x) (((((x))*219)>>8)+16)
#define CLIP(t) (((t)>255)?255:(((t)<0)?0:(t)))
#define GETY(r,g,b) UNFIX((FIX(0.299,FIXNUM)*(r)+\
FIX(0.587,FIXNUM)*(g)+\
FIX(0.144,FIXNUM)*(b)),FIXNUM)
#define GETU(r,g,b) UNFIX((FIX(-0.1687,FIXNUM)*(r)+\
FIX(-0.3313,FIXNUM)*(g)+\
FIX(0.5,FIXNUM)*(b)),FIXNUM)
#define GETV(r,g,b) UNFIX((FIX(0.5,FIXNUM)*(r)+\
FIX(-0.4187,FIXNUM)*(g)+\
FIX(-0.0813,FIXNUM)*(b)),FIXNUM)
char *suffix[3] = {".Y",".U",".V"};
void convertRGB2YUV(FILE *inp,FILE *outy, FILE *outu,FILE *outv, int CCIR601);
void
convertRGB2YUV(inp, outy, outu, outv, CCIR601)
FILE *inp,*outy,*outu,*outv;
int CCIR601;
{
int i,j;
int r1,r2,r3,r4,g1,g2,g3,g4,b1,b2,b3,b4;
int magic1, magic2;
int incols,inrows,maxval;
int outcols,outrows;
int temp;
char inpstring[256];
unsigned char *temprgb1, *temprgb2, *tempy1, *tempy2, *tempu, *tempv;
unsigned char *rgb1p, *rgb2p, *y1p, *y2p, *up, *vp;
magic1=fgetc(inp);
magic2=fgetc(inp);
fgetc(inp); /* dispense with \n */
fgets(inpstring,256,inp);
sscanf(inpstring,"%d %d",&incols, &inrows);
fgets(inpstring,256,inp);
sscanf(inpstring,"%d",&maxval);
/* printf("%d %d %d %d %d\n",magic1,magic2,incols,inrows,maxval); */
if (maxval>255)
{
printf("Only handles maximum value of 255 < (found)%d\n",maxval);
exit(0);
}
if (magic1 != PPM_MAGIC1)
{
printf("Bad magic number 1; not ppm file?\n");
exit(0);
}
if (magic2 != RPPM_MAGIC2)
{
printf("Bad magic number 2; not raw ppm file?\n");
exit(0);
}
if (inrows&1) outrows = inrows-1;
else outrows = inrows;
if (incols&1) outcols = incols-1;
else outcols = incols;
printf("input size: %dx%d\t output size: %dx%d\n",
incols,inrows,outcols,outrows);
temprgb1 = (unsigned char *) calloc(incols*3,sizeof(char));
temprgb2 = (unsigned char *) calloc(incols*3,sizeof(char));
tempy1 = (unsigned char *) calloc(outcols,sizeof(char));
tempy2 = (unsigned char *) calloc(outcols,sizeof(char));
tempu = (unsigned char *) calloc(outcols>>1,sizeof(char));
tempv = (unsigned char *) calloc(outcols>>1,sizeof(char));
for(i=0;i<(outrows>>1);i++)
{
fread(temprgb1,1,incols*3*sizeof(char),inp);
fread(temprgb2,1,incols*3*sizeof(char),inp);
rgb1p = temprgb1;
rgb2p = temprgb2;
y1p = tempy1;
y2p = tempy2;
up = tempu;
vp = tempv;
for(j=0;j<(outcols>>1);j++)
{
r1 = *(rgb1p++);
g1 = *(rgb1p++);
b1 = *(rgb1p++);
r2 = *(rgb1p++);
g2 = *(rgb1p++);
b2 = *(rgb1p++);
r3 = *(rgb2p++);
g3 = *(rgb2p++);
b3 = *(rgb2p++);
r4 = *(rgb2p++);
g4 = *(rgb2p++);
b4 = *(rgb2p++);
if (CCIR601)
{
temp=GETY(r1,g1,b1);
temp=CLIP(temp);
*(y1p++) = CCIRY(temp);
temp=GETY(r2,g2,b2);
temp=CLIP(temp);
*(y1p++) = CCIRY(temp);
temp=GETY(r3,g3,b3);
temp=CLIP(temp);
*(y2p++) = CCIRY(temp);
temp=GETY(r4,g4,b4);
temp=CLIP(temp);
*(y2p++) = CCIRY(temp);
/* We use a box filter for decimation */
temp = ((GETU(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
+(1<<9)+(1<<1))>>2);
temp=CLIP(temp);
*(up++) = CCIRUV(temp);
temp = ((GETV(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
+(1<<9)+(1<<1))>>2);
temp=CLIP(temp);
*(vp++) = CCIRUV(temp);
}
else
{
temp=GETY(r1,g1,b1);
*(y1p++) = CLIP(temp);
temp=GETY(r2,g2,b2);
*(y1p++) = CLIP(temp);
temp=GETY(r3,g3,b3);
*(y2p++) = CLIP(temp);
temp=GETY(r4,g4,b4);
*(y2p++) = CLIP(temp);
/* We use a box filter for decimation */
temp = ((GETU(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
+(1<<9)+(1<<1))>>2);
*(up++) = CLIP(temp);
temp = ((GETV(r1+r2+r3+r4,g1+g2+g3+g4,b1+b2+b3+b4)
+(1<<9)+(1<<1))>>2);
*(vp++) = CLIP(temp);
}
}
fwrite(tempy1,1,outcols*sizeof(char),outy);
fwrite(tempy2,1,outcols*sizeof(char),outy);
fwrite(tempu,1,(outcols>>1)*sizeof(char),outu);
fwrite(tempv,1,(outcols>>1)*sizeof(char),outv);
}
}
int
main(argc, argv)
int argc;
char **argv;
{
int i;
int CCIR601=0;
int suffixcount=0;
char *infile,*outfile;
char outfiley[256];
char outfileu[256];
char outfilev[256];
FILE *inp,*outy,*outu,*outv;
if (argc<3)
{
printf("ppm2cyuv infile outfile [-z suffix]* [-CCIR601]\n");
printf("\n");
printf("infile is the input ppm file\n");
printf("outfile is the output file with outfile.Y outfile.U outfile.V\n");
printf("-z specifies alternate suffixes:\n");
printf(" e.g. ppm2cyuv inp.ppm out -z .y -z .cb -z .cr\n");
printf(" will output out.y, out.cb, out.cr, respectively\n");
printf("-CCIR601 specifies CCIR601 yuv space (default JFIF).\n");
exit(0);
}
for(i=3;i<argc;i++)
{
if (!strcmp(argv[i],"-z"))
{
if (suffixcount==3)
{
printf("too many suffixes\n");
exit(0);
}
suffix[suffixcount++] = argv[++i];
}
else if (!strcmp(argv[i],"-CCIR601"))
CCIR601=1;
else
{
printf("unknown option: %s\n",argv[i]);
exit(0);
}
}
infile = argv[1];
outfile = argv[2];
sprintf(outfiley,"%s%s",outfile,suffix[0]);
sprintf(outfileu,"%s%s",outfile,suffix[1]);
sprintf(outfilev,"%s%s",outfile,suffix[2]);
if (!(inp=fopen(infile,"r")))
{
printf("cannot open file: %s\n",infile);
exit(0);
}
if (!(outy=fopen(outfiley,"w")))
{
printf("cannot open file: %s\n",outfiley);
exit(0);
}
if (!(outu=fopen(outfileu,"w")))
{
printf("cannot open file: %s\n",outfileu);
exit(0);
}
if (!(outv=fopen(outfilev,"w")))
{
printf("cannot open file: %s\n",outfilev);
exit(0);
}
convertRGB2YUV(inp,outy,outu,outv,CCIR601);
exit(0);
}